#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
英文文档翻译工具 - PyQt桌面版
基于Flask应用功能创建的桌面应用程序
"""

import os
import sys
import tempfile
import threading
import time
import subprocess
import shutil
import random
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QLabel, QPushButton, QProgressBar, QFileDialog, QMessageBox,
                             QCheckBox, QTextEdit, QGroupBox, QTabWidget, QListWidget,
                             QListWidgetItem, QSplitter, QFrame, QComboBox)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QIcon, QPalette, QColor
from doc_trans import translate_document, get_document_paragraph_count

# 平台检测和兼容性处理
if sys.platform == "win32":
    # Windows系统使用Microsoft Word COM接口
    try:
        import win32com.client
        import pythoncom
        HAS_WIN32COM = True
    except ImportError:
        HAS_WIN32COM = False
        print("警告: 未安装pywin32库，DOC文件转换功能将不可用")
else:
    # Linux/Mac系统使用LibreOffice或在线转换服务
    HAS_WIN32COM = False


class TranslationThread(QThread):
    """翻译任务线程"""
    progress_updated = pyqtSignal(int, int, int)  # progress, current, total
    task_completed = pyqtSignal(str, str)  # task_id, output_path
    task_failed = pyqtSignal(str, str)  # task_id, error_message
    task_cancelled = pyqtSignal(str)  # task_id
    
    def __init__(self, task_id, input_path, output_path, translate_tables, translation_direction, original_filename):
        super().__init__()
        self.task_id = task_id
        self.input_path = input_path
        self.output_path = output_path
        self.translate_tables = translate_tables
        self.translation_direction = translation_direction
        self.original_filename = original_filename
        self._is_cancelled = False
    
    def cancel(self):
        """取消翻译任务"""
        self._is_cancelled = True
    
    def run(self):
        """执行翻译任务"""
        try:
            # 获取文档总工作量（段落数 + 表格单元格数）
            total_paragraphs = get_document_paragraph_count(self.input_path, self.translate_tables)
            
            # 更新初始进度
            self.progress_updated.emit(0, 0, total_paragraphs)
            
            # 翻译文档（传递进度回调）
            def progress_callback(progress, current, total):
                # 检查任务是否被取消
                if self._is_cancelled:
                    raise Exception("翻译任务已被用户取消")
                self.progress_updated.emit(progress, current, total)
            
            translate_document(self.input_path, self.output_path, 
                              translate_tables=self.translate_tables,
                              translation_direction=self.translation_direction,
                              progress_callback=progress_callback)
            
            # 标记任务完成
            self.progress_updated.emit(100, total_paragraphs, total_paragraphs)
            self.task_completed.emit(self.task_id, self.output_path)
            
            # 清理临时输入文件
            if os.path.exists(self.input_path):
                os.unlink(self.input_path)
            
        except Exception as e:
            # 检查是否是取消操作
            if self._is_cancelled:
                self.task_cancelled.emit(self.task_id)
                # 清理临时文件
                if os.path.exists(self.input_path):
                    os.unlink(self.input_path)
                if os.path.exists(self.output_path):
                    os.unlink(self.output_path)
            else:
                self.task_failed.emit(self.task_id, str(e))
                # 清理临时文件
                if os.path.exists(self.input_path):
                    os.unlink(self.input_path)


class MainWindow(QMainWindow):
    """主窗口类"""
    
    def __init__(self):
        super().__init__()
        
        # 初始化变量
        self.current_task_id = None
        self.translation_thread = None
        self.running_tasks = {}
        self.completed_tasks = {}
        self.failed_tasks = {}
        
        # 设置窗口属性
        self.setWindowTitle("文档翻译工具 - PyQt桌面版")
        self.setGeometry(100, 100, 900, 700)
        
        # 设置样式
        self.setup_styles()
        
        # 创建界面
        self.setup_ui()
        
        # 启动定时清理任务
        self.init_cleanup_scheduler()
        
        # 创建必要的目录
        self.create_directories()
    
    def setup_styles(self):
        """设置应用样式"""
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QGroupBox {
                font-weight: bold;
                border: 2px solid #cccccc;
                border-radius: 8px;
                margin-top: 10px;
                padding-top: 10px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px 0 5px;
            }
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                border-radius: 6px;
                padding: 8px 16px;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QPushButton:disabled {
                background-color: #cccccc;
                color: #666666;
            }
            QProgressBar {
                border: 1px solid #cccccc;
                border-radius: 4px;
                text-align: center;
            }
            QProgressBar::chunk {
                background-color: #4CAF50;
                border-radius: 3px;
            }
        """)
    
    def setup_ui(self):
        """创建用户界面"""
        # 创建中央窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 创建标题
        title_label = QLabel("英文文档翻译工具")
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setFont(QFont("Arial", 16, QFont.Bold))
        title_label.setStyleSheet("color: #2c3e50; margin: 20px;")
        main_layout.addWidget(title_label)
        
        # 创建选项卡
        tab_widget = QTabWidget()
        main_layout.addWidget(tab_widget)
        
        # 翻译选项卡
        self.setup_translation_tab(tab_widget)
        
        # 任务管理选项卡
        self.setup_tasks_tab(tab_widget)
        
        # 设置选项卡
        self.setup_settings_tab(tab_widget)
    
    def setup_translation_tab(self, tab_widget):
        """设置翻译选项卡"""
        translation_tab = QWidget()
        layout = QVBoxLayout(translation_tab)
        
        # 文件选择区域
        file_group = QGroupBox("文件选择")
        file_layout = QVBoxLayout(file_group)
        
        # 文件选择按钮
        file_button_layout = QHBoxLayout()
        self.select_file_button = QPushButton("选择文档文件")
        self.select_file_button.clicked.connect(self.select_file)
        file_button_layout.addWidget(self.select_file_button)
        
        self.selected_file_label = QLabel("未选择文件")
        self.selected_file_label.setStyleSheet("color: #666666; font-style: italic;")
        file_button_layout.addWidget(self.selected_file_label)
        file_button_layout.addStretch()
        
        file_layout.addLayout(file_button_layout)
        layout.addWidget(file_group)
        
        # 选项区域
        options_group = QGroupBox("翻译选项")
        options_layout = QVBoxLayout(options_group)
        
        # 翻译方向选择
        direction_layout = QHBoxLayout()
        direction_label = QLabel("翻译方向：")
        self.translation_direction_combo = QComboBox()
        self.translation_direction_combo.addItem("英文 → 中文", "en_to_zh")
        self.translation_direction_combo.addItem("中文 → 英文", "zh_to_en")
        direction_layout.addWidget(direction_label)
        direction_layout.addWidget(self.translation_direction_combo)
        direction_layout.addStretch()
        options_layout.addLayout(direction_layout)
        
        self.translate_tables_checkbox = QCheckBox("翻译表格内容")
        self.translate_tables_checkbox.setChecked(False)
        options_layout.addWidget(self.translate_tables_checkbox)
        
        layout.addWidget(options_group)
        
        # 进度显示区域
        progress_group = QGroupBox("翻译进度")
        progress_layout = QVBoxLayout(progress_group)
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        progress_layout.addWidget(self.progress_bar)
        
        self.progress_label = QLabel("准备开始翻译...")
        self.progress_label.setAlignment(Qt.AlignCenter)
        progress_layout.addWidget(self.progress_label)
        
        layout.addWidget(progress_group)
        
        # 按钮区域
        button_layout = QHBoxLayout()
        
        self.start_button = QPushButton("开始翻译")
        self.start_button.clicked.connect(self.start_translation)
        self.start_button.setEnabled(False)
        button_layout.addWidget(self.start_button)
        
        self.cancel_button = QPushButton("取消翻译")
        self.cancel_button.clicked.connect(self.cancel_translation)
        self.cancel_button.setEnabled(False)
        button_layout.addWidget(self.cancel_button)
        
        self.download_button = QPushButton("下载翻译结果")
        self.download_button.clicked.connect(self.download_translation)
        self.download_button.setEnabled(False)
        button_layout.addWidget(self.download_button)
        
        layout.addLayout(button_layout)
        layout.addStretch()
        
        tab_widget.addTab(translation_tab, "文档翻译")
    
    def setup_tasks_tab(self, tab_widget):
        """设置任务管理选项卡"""
        tasks_tab = QWidget()
        layout = QVBoxLayout(tasks_tab)
        
        # 任务列表
        tasks_group = QGroupBox("任务列表")
        tasks_layout = QVBoxLayout(tasks_group)
        
        self.tasks_list = QListWidget()
        tasks_layout.addWidget(self.tasks_list)
        
        # 任务操作按钮
        task_buttons_layout = QHBoxLayout()
        
        self.refresh_tasks_button = QPushButton("刷新列表")
        self.refresh_tasks_button.clicked.connect(self.refresh_tasks_list)
        task_buttons_layout.addWidget(self.refresh_tasks_button)
        
        self.clear_completed_button = QPushButton("清理已完成任务")
        self.clear_completed_button.clicked.connect(self.clear_completed_tasks)
        task_buttons_layout.addWidget(self.clear_completed_button)
        
        tasks_layout.addLayout(task_buttons_layout)
        layout.addWidget(tasks_group)
        
        tab_widget.addTab(tasks_tab, "任务管理")
    
    def setup_settings_tab(self, tab_widget):
        """设置设置选项卡"""
        settings_tab = QWidget()
        layout = QVBoxLayout(settings_tab)
        
        # 清理设置
        cleanup_group = QGroupBox("文件清理设置")
        cleanup_layout = QVBoxLayout(cleanup_group)
        
        cleanup_buttons_layout = QHBoxLayout()
        
        self.manual_cleanup_button = QPushButton("手动清理旧文件")
        self.manual_cleanup_button.clicked.connect(self.manual_cleanup)
        cleanup_buttons_layout.addWidget(self.manual_cleanup_button)
        
        self.auto_cleanup_toggle = QPushButton("停止自动清理")
        self.auto_cleanup_toggle.clicked.connect(self.toggle_auto_cleanup)
        cleanup_buttons_layout.addWidget(self.auto_cleanup_toggle)
        
        cleanup_layout.addLayout(cleanup_buttons_layout)
        
        self.cleanup_status_label = QLabel("自动清理状态: 运行中")
        cleanup_layout.addWidget(self.cleanup_status_label)
        
        layout.addWidget(cleanup_group)
        layout.addStretch()
        
        tab_widget.addTab(settings_tab, "设置")
    
    def create_directories(self):
        """创建必要的目录"""
        os.makedirs("output", exist_ok=True)
        os.makedirs("extracted_images", exist_ok=True)
    
    def select_file(self):
        """选择文件"""
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择文档文件", "", "Word文档 (*.doc *.docx)")
        
        if file_path:
            self.selected_file_path = file_path
            filename = os.path.basename(file_path)
            self.selected_file_label.setText(f"已选择: {filename}")
            self.start_button.setEnabled(True)
    
    def start_translation(self):
        """开始翻译"""
        if not hasattr(self, 'selected_file_path'):
            QMessageBox.warning(self, "警告", "请先选择文件")
            return
        
        # 生成任务ID
        self.current_task_id = f"{int(time.time() * 1000)}_{random.randint(1000, 9999)}"
        
        # 准备输出文件路径
        original_filename = os.path.basename(self.selected_file_path)
        unique_output_filename = f"translated_{self.current_task_id}_{original_filename}"
        output_path = os.path.join("output", unique_output_filename)
        
        # 复制文件到临时位置（避免原始文件被占用）
        temp_input_path = os.path.join(tempfile.gettempdir(), f"temp_{self.current_task_id}.docx")
        shutil.copy2(self.selected_file_path, temp_input_path)
        
        # 如果是DOC文件，先转换为DOCX
        if self.selected_file_path.endswith('.doc'):
            converted_path = self.convert_doc_to_docx(temp_input_path)
            if converted_path:
                os.remove(temp_input_path)
                temp_input_path = converted_path
            else:
                QMessageBox.critical(self, "错误", "DOC文件转换失败")
                return
        
        # 启动翻译线程
        self.translation_thread = TranslationThread(
            self.current_task_id, temp_input_path, output_path,
            self.translate_tables_checkbox.isChecked(), 
            self.translation_direction_combo.currentData(), original_filename
        )
        
        # 连接信号
        self.translation_thread.progress_updated.connect(self.update_progress)
        self.translation_thread.task_completed.connect(self.translation_completed)
        self.translation_thread.task_failed.connect(self.translation_failed)
        self.translation_thread.task_cancelled.connect(self.translation_cancelled)
        
        # 更新UI状态
        self.start_button.setEnabled(False)
        self.cancel_button.setEnabled(True)
        self.download_button.setEnabled(False)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.progress_label.setText("翻译任务已开始...")
        
        # 添加到运行任务列表
        self.running_tasks[self.current_task_id] = {
            'filename': original_filename,
            'start_time': time.time()
        }
        
        # 启动线程
        self.translation_thread.start()
    
    def cancel_translation(self):
        """取消翻译"""
        if self.translation_thread and self.translation_thread.isRunning():
            reply = QMessageBox.question(self, "确认取消", 
                                       "确定要取消当前翻译任务吗？",
                                       QMessageBox.Yes | QMessageBox.No)
            
            if reply == QMessageBox.Yes:
                self.translation_thread.cancel()
                self.progress_label.setText("正在取消翻译任务...")
    
    def download_translation(self):
        """下载翻译结果"""
        if hasattr(self, 'current_output_path') and os.path.exists(self.current_output_path):
            # 让用户选择保存位置
            save_path, _ = QFileDialog.getSaveFileName(
                self, "保存翻译结果", "", "Word文档 (*.docx)")
            
            if save_path:
                if not save_path.endswith('.docx'):
                    save_path += '.docx'
                
                try:
                    shutil.copy2(self.current_output_path, save_path)
                    QMessageBox.information(self, "成功", f"文件已保存到: {save_path}")
                except Exception as e:
                    QMessageBox.critical(self, "错误", f"保存文件失败: {str(e)}")
        else:
            QMessageBox.warning(self, "警告", "没有可下载的翻译结果")
    
    def update_progress(self, progress, current, total):
        """更新进度显示"""
        self.progress_bar.setValue(progress)
        self.progress_label.setText(f"翻译进度: {current}/{total} ({progress}%)")
    
    def translation_completed(self, task_id, output_path):
        """翻译完成"""
        self.current_output_path = output_path
        
        # 更新任务状态
        if task_id in self.running_tasks:
            task_info = self.running_tasks.pop(task_id)
            self.completed_tasks[task_id] = task_info
        
        # 更新UI
        self.start_button.setEnabled(True)
        self.cancel_button.setEnabled(False)
        self.download_button.setEnabled(True)
        self.progress_label.setText("翻译完成！")
        
        QMessageBox.information(self, "完成", "文档翻译已完成！")
        
        # 刷新任务列表
        self.refresh_tasks_list()
    
    def translation_failed(self, task_id, error_message):
        """翻译失败"""
        # 更新任务状态
        if task_id in self.running_tasks:
            task_info = self.running_tasks.pop(task_id)
            self.failed_tasks[task_id] = {**task_info, 'error': error_message}
        
        # 更新UI
        self.start_button.setEnabled(True)
        self.cancel_button.setEnabled(False)
        self.download_button.setEnabled(False)
        self.progress_bar.setVisible(False)
        self.progress_label.setText(f"翻译失败: {error_message}")
        
        QMessageBox.critical(self, "错误", f"翻译失败: {error_message}")
        
        # 刷新任务列表
        self.refresh_tasks_list()
    
    def translation_cancelled(self, task_id):
        """翻译被取消"""
        # 更新任务状态
        if task_id in self.running_tasks:
            self.running_tasks.pop(task_id)
        
        # 更新UI
        self.start_button.setEnabled(True)
        self.cancel_button.setEnabled(False)
        self.download_button.setEnabled(False)
        self.progress_bar.setVisible(False)
        self.progress_label.setText("翻译任务已取消")
        
        QMessageBox.information(self, "取消", "翻译任务已取消")
        
        # 刷新任务列表
        self.refresh_tasks_list()
    
    def refresh_tasks_list(self):
        """刷新任务列表"""
        self.tasks_list.clear()
        
        # 添加运行中的任务
        for task_id, task_info in self.running_tasks.items():
            item = QListWidgetItem(f"🔄 运行中: {task_info['filename']} (ID: {task_id})")
            self.tasks_list.addItem(item)
        
        # 添加已完成的任务
        for task_id, task_info in self.completed_tasks.items():
            item = QListWidgetItem(f"✅ 已完成: {task_info['filename']} (ID: {task_id})")
            self.tasks_list.addItem(item)
        
        # 添加失败的任务
        for task_id, task_info in self.failed_tasks.items():
            item = QListWidgetItem(f"❌ 失败: {task_info['filename']} (ID: {task_id})")
            self.tasks_list.addItem(item)
    
    def clear_completed_tasks(self):
        """清理已完成任务"""
        self.completed_tasks.clear()
        self.failed_tasks.clear()
        self.refresh_tasks_list()
        QMessageBox.information(self, "成功", "已完成任务已清理")
    
    def manual_cleanup(self):
        """手动清理旧文件"""
        try:
            self.cleanup_old_files()
            QMessageBox.information(self, "成功", "手动清理完成")
        except Exception as e:
            QMessageBox.critical(self, "错误", f"清理失败: {str(e)}")
    
    def toggle_auto_cleanup(self):
        """切换自动清理状态"""
        if self.cleanup_running:
            self.stop_cleanup_scheduler()
            self.auto_cleanup_toggle.setText("启动自动清理")
            self.cleanup_status_label.setText("自动清理状态: 已停止")
        else:
            self.init_cleanup_scheduler()
            self.auto_cleanup_toggle.setText("停止自动清理")
            self.cleanup_status_label.setText("自动清理状态: 运行中")
    
    def convert_doc_to_docx(self, doc_path):
        """将DOC文件转换为DOCX格式"""
        docx_path = doc_path.replace('.doc', '.docx')
        
        if sys.platform == "win32" and HAS_WIN32COM:
            # Windows系统使用Microsoft Word COM接口
            try:
                pythoncom.CoInitialize()
                word = win32com.client.Dispatch("Word.Application")
                word.Visible = False
                
                doc = word.Documents.Open(doc_path)
                doc.SaveAs(docx_path, FileFormat=16)  # 16代表DOCX格式
                doc.Close()
                word.Quit()
                pythoncom.CoUninitialize()
                
                return docx_path
                
            except Exception as e:
                print(f"DOC文件转换失败: {e}")
                try:
                    pythoncom.CoUninitialize()
                except:
                    pass
        else:
            # Linux/Mac系统使用LibreOffice命令行转换
            try:
                result = subprocess.run(['which', 'libreoffice'], capture_output=True, text=True)
                if result.returncode == 0:
                    cmd = [
                        'libreoffice', '--headless', '--convert-to', 'docx',
                        '--outdir', os.path.dirname(docx_path), doc_path
                    ]
                    result = subprocess.run(cmd, capture_output=True, text=True)
                    
                    if result.returncode == 0:
                        return docx_path
                
            except Exception as e:
                print(f"Linux系统DOC转换失败: {e}")
        
        return None
    
    def cleanup_old_files(self):
        """清理旧文件"""
        current_time = time.time()
        cleanup_interval = 24 * 60 * 60  # 24小时
        
        # 清理extracted_images目录
        extracted_images_dir = "extracted_images"
        if os.path.exists(extracted_images_dir):
            try:
                for root, dirs, files in os.walk(extracted_images_dir):
                    for file in files:
                        file_path = os.path.join(root, file)
                        file_mtime = os.path.getmtime(file_path)
                        if current_time - file_mtime > cleanup_interval:
                            os.unlink(file_path)
                
                if not os.listdir(extracted_images_dir):
                    shutil.rmtree(extracted_images_dir)
            except Exception as e:
                print(f"清理extracted_images目录时出错: {e}")
        
        # 清理output目录中的旧文件
        output_dir = "output"
        if os.path.exists(output_dir):
            try:
                for file in os.listdir(output_dir):
                    file_path = os.path.join(output_dir, file)
                    if os.path.isfile(file_path):
                        file_mtime = os.path.getmtime(file_path)
                        if current_time - file_mtime > cleanup_interval:
                            os.unlink(file_path)
            except Exception as e:
                print(f"清理output目录时出错: {e}")
    
    def init_cleanup_scheduler(self):
        """初始化定时清理任务"""
        self.cleanup_running = True
        self.cleanup_thread = threading.Thread(target=self.cleanup_scheduler_worker, daemon=True)
        self.cleanup_thread.start()
    
    def stop_cleanup_scheduler(self):
        """停止定时清理任务"""
        self.cleanup_running = False
    
    def cleanup_scheduler_worker(self):
        """定时清理任务的工作线程"""
        while self.cleanup_running:
            try:
                self.cleanup_old_files()
                time.sleep(24 * 60 * 60)  # 等待24小时
            except Exception as e:
                print(f"定时清理任务执行出错: {e}")
                time.sleep(60 * 60)  # 出错后等待1小时再重试
    
    def closeEvent(self, event):
        """窗口关闭事件"""
        # 停止所有运行中的任务
        if self.translation_thread and self.translation_thread.isRunning():
            reply = QMessageBox.question(self, "确认退出", 
                                       "有翻译任务正在运行，确定要退出吗？",
                                       QMessageBox.Yes | QMessageBox.No)
            
            if reply == QMessageBox.No:
                event.ignore()
                return
            
            # 取消翻译任务
            self.translation_thread.cancel()
            self.translation_thread.wait(5000)  # 等待5秒
        
        # 停止清理任务
        self.stop_cleanup_scheduler()
        
        event.accept()


def main():
    """主函数"""
    app = QApplication(sys.argv)
    
    # 设置应用样式
    app.setStyle('Fusion')
    
    # 创建主窗口
    window = MainWindow()
    window.show()
    
    # 运行应用
    sys.exit(app.exec_())


if __name__ == "__main__":
    main()